package org.budo.sentinel.adapter.dubbo;

import org.budo.dubbo.rpc.util.InvocationUtil;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;

/**
 * 去掉接口级别，只保留方法级别，方法签名替换为budo-graph一致的方案
 * 
 * @author lmw
 * @see com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboConsumerFilter
 */
@Activate(group = "consumer")
public class BudoSentinelDubboConsumerFilter implements Filter {
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Entry entry = null;
        try {
            String resourceName = InvocationUtil.invocationToRequestUri(invocation);
            entry = SphU.entry(resourceName, EntryType.OUT);

            Result result = invoker.invoke(invocation);
            if (result.hasException()) {
                Tracer.trace(result.getException());
            }
            return result;
        } catch (BlockException e) {
            throw new SentinelRpcException(e);
        } catch (RpcException e) {
            Tracer.trace(e);
            throw e;
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }
}